home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / info-service / gopher / Unix / xgopher.1.3 / net.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-08  |  8.2 KB  |  405 lines

  1. /* net.c
  2.    network and socket maintenance procedures */
  3.  
  4.      /*---------------------------------------------------------------*/
  5.      /* Xgopher        version 1.3     08 April 1993                  */
  6.      /*                version 1.2     20 November 1992               */
  7.      /*                version 1.1     20 April 1992                  */
  8.      /*                version 1.0     04 March 1992                  */
  9.      /* X window system client for the University of Minnesota        */
  10.      /*                                Internet Gopher System.        */
  11.      /* Allan Tuchman, University of Illinois at Urbana-Champaign     */
  12.      /*                Computing and Communications Services Office   */
  13.      /* Copyright 1992, 1993 by                                       */
  14.      /*           the Board of Trustees of the University of Illinois */
  15.      /* Permission is granted to freely copy and redistribute this    */
  16.      /* software with the copyright notice intact.                    */
  17.      /*---------------------------------------------------------------*/
  18.  
  19.  
  20. /* The header files here need to be checked and corrected on almost
  21.    a per-machine basis. */
  22.  
  23. #include <stdio.h>
  24.  
  25. #ifndef IS_BSD
  26. #include <stdlib.h>
  27. #endif
  28.  
  29. #include <sys/types.h>
  30. #include <sys/socket.h>
  31. #include <netinet/in.h>
  32.  
  33. #ifndef IS_A_HPUX
  34. #include <arpa/inet.h>
  35. #endif
  36.  
  37. #include <netdb.h>
  38. #include <signal.h>
  39.  
  40. #include <ctype.h>
  41. #include <errno.h>
  42. #include <time.h>
  43.  
  44. #include <sys/param.h>
  45. #include "gopher.h"
  46. #include "globals.h"
  47. #include "osdep.h"
  48.  
  49.  
  50. /* <netinet/in.h> should define INADDR_NONE for a failed return
  51.    from inet_addr().  Just in case it is not defined on some machine
  52.    it is defined here to -1.  Most machines return a -1.  If this
  53.    assumption is false, we're lost anyway and a hand change is needed. */
  54.  
  55. #ifndef INADDR_NONE
  56. #define INADDR_NONE    -1
  57. #endif
  58.  
  59.  
  60. /* connectToSocket
  61.    performs a connection to socket 'port' on host 'host'.
  62.   
  63.    Errors: 
  64.        -2 get host failed
  65.        -3 socket call failed
  66.        -4 connect call failed
  67.  */
  68.  
  69. static struct sockaddr_in server;
  70. struct hostent *hostPtr;
  71.  
  72. /* OS dependencies:
  73.  
  74.    . gethostname(char *, int) is a Unix kernel call to return the
  75.      address of a string containing the local host name.
  76.    . MAXHOSTNAMELEN is set in <sys/param.h> to be the maximum host name
  77.      size.  This is often 64 for BSD Unix.
  78.  
  79. */
  80.  
  81. int
  82. connectToSocket(host, port)
  83. char *host;
  84. int  port;
  85. {
  86.     /* Host can be a hostname or ip-address.
  87.        If 'host' is null, the local host is assumed. */
  88.  
  89.     int    iSock = 0;
  90.     char    hostName[MAXHOSTNAMELEN];
  91.  
  92.     LOG(logFP, "Connecting to \'%s\' at port %d\n", host, port);
  93.     if (host == '\0') {
  94.         gethostname(hostName, MAXHOSTNAMELEN);
  95.         host = hostName;
  96.     }
  97.  
  98.     if ((server.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
  99.         if ((hostPtr = gethostbyname(host)) != NULL) {
  100.             bzero((char *) &server, sizeof(server));
  101.             bcopy(hostPtr->h_addr, (char *) &server.sin_addr,
  102.                         hostPtr->h_length);
  103.             server.sin_family = hostPtr->h_addrtype;
  104.         } else {
  105.             return (-2);
  106.         }
  107.     } else {
  108.         server.sin_family = AF_INET;
  109.     }
  110.  
  111.     server.sin_port = (unsigned short) htons(port);
  112.  
  113.     /* in the socket call, should AF_INET be replaced with 
  114.        server.sin_family? */
  115.  
  116.     if ((iSock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  117.         return (-3);
  118.  
  119.     setsockopt(iSock, SOL_SOCKET, ~SO_LINGER, 0, 0);
  120.     setsockopt(iSock, SOL_SOCKET, SO_REUSEADDR, 0, 0);
  121.     setsockopt(iSock, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
  122.  
  123.     if (connect(iSock, (struct sockaddr *) &server, sizeof(server)) < 0) {
  124.         close(iSock);
  125.         return (-4);
  126.     }
  127.     return(iSock);
  128. }
  129.  
  130.  
  131. /* networkError
  132.    Checks the return value from connectToSoocket and report any error */
  133.  
  134. void
  135. networkError(gfd, host, port)
  136. int gfd;
  137. char *host;
  138. {
  139.      char errorString[MESSAGE_STRING_LEN];
  140. #define NET_ERROR_MESSAGE "Cannot establish a network connection"
  141.  
  142.      switch(gfd)  {
  143.      case -4:
  144.       if (port != 0)
  145.           (void) sprintf(errorString,
  146.             "%s\n(could not connect to remote computer \'%s\' at port %d)",
  147.             NET_ERROR_MESSAGE, host, port);
  148.       else
  149.           (void) sprintf(errorString,
  150.         "%s\n(could not connect to remote computer \'%s\')",
  151.             NET_ERROR_MESSAGE, host);
  152.           break;
  153.      case -3:
  154.       (void) sprintf(errorString,
  155.             "%s\n(because socket failed)",
  156.             NET_ERROR_MESSAGE);
  157.       break;
  158.      case -2:
  159.       (void) sprintf(errorString,
  160.             "%s\n(could not identify the remote host computer \'%s\')",
  161.             NET_ERROR_MESSAGE, host);
  162.       break;
  163.      }
  164.      
  165.      if (gfd < 0) {
  166.       showError(errorString);
  167.      }
  168. }
  169.  
  170. /* ----- */
  171.  
  172. /* Read "n" bytes from a descriptor.
  173.  * Use in place of read() when fd is a stream socket
  174.  *
  175.  * Returns the number of total bytes read.
  176.  */
  177.  
  178. int readn(fd, ptr, nbytes)
  179. int fd;
  180. char *ptr;
  181. int nbytes;
  182. {
  183.     int nleft, nread;
  184.  
  185.     nleft = nbytes;
  186.     while (nleft > 0) {
  187.         nread = read(fd, ptr, nleft);
  188.         if (nread < 0)
  189.             return(nread);    /* error, return <0 */
  190.         else if (nread == 0)    /* EOF */
  191.             break;
  192.     
  193.         nleft     -= nread;
  194.         ptr     += nread;
  195.     }
  196.     return(nbytes - nleft);    /* return >= 0) */
  197. }
  198.  
  199.  
  200.  
  201. /*
  202.  * Write "n" bytes to a descriptor.
  203.  * Use in place of write() when fd is a stream socket
  204.  *
  205.  * We return the number of bytes written
  206.  */
  207.  
  208. int writen(fd, ptr, nbytes)
  209. int    fd;
  210. char    *ptr;
  211. int    nbytes;
  212. {
  213.     int nleft, nwritten;
  214.  
  215.     nleft = nbytes;
  216.     while(nleft > 0) {
  217.         nwritten = write(fd, ptr, nleft);
  218.         if (nwritten <= 0)
  219.             return(nwritten);    /* error */
  220.  
  221.         nleft    -= nwritten;
  222.         ptr    += nwritten;
  223.     }
  224.     return(nbytes - nleft);
  225. }
  226.  
  227.  
  228. /*
  229.  * Writestring uses the writen and strlen calls to write a
  230.  * string to the file descriptor fd.  If the write fails
  231.  * a -1 is returned. Otherwise zero is returned.
  232.  */
  233.  
  234. int writeString(fd, stringptr)
  235. int    fd;
  236. char    *stringptr;
  237. {
  238.     int length;
  239.  
  240.     length = strlen(stringptr);
  241.     if (writen(fd, stringptr, length) != length)
  242.         return(-1);
  243.     else
  244.         return(0);
  245. }
  246.  
  247.  
  248. /*
  249.  * Read a line from a descriptor.  Read the line one byte at a time,
  250.  * looking for the newline.  We store the newline in the buffer,
  251.  * then follow it with a null (the same as fgets(3)).
  252.  * We return the number of characters up to, but not including,
  253.  * the null (the same as strlen(3))
  254.  */
  255.  
  256. int readLine(fd, ptr, maxlen)
  257. int    fd;
  258. char    *ptr;
  259. int     maxlen;
  260. {
  261.     int n;
  262.     int rc;
  263.     char c;
  264.  
  265.     for (n=1; n < maxlen; n++) {
  266.         if ( (rc = read(fd, &c, 1)) == 1) {
  267.             *ptr++ = c;
  268.             if (c == '\n')
  269.                 break;
  270.         }
  271.         else if (rc == 0) {
  272.             if (n == 1)
  273.                 return(0);    /* EOF, no data read */
  274.             else
  275.                 break;        /* EOF, some data was read */
  276.         }
  277.         else
  278.             return(-1);        /* error */
  279.     }
  280.  
  281.     *ptr = 0;                 /* Tack a NULL on the end */
  282.     return(n);
  283. }
  284.  
  285. /*
  286.  * Readfield reads data up to a tab, (like readline above)
  287.  */
  288.  
  289. int readField(fd, ptr, maxlen)
  290. int    fd;
  291. char    *ptr;
  292. int     maxlen;
  293. {
  294.     int n;
  295.     int rc;
  296.     char c;
  297.  
  298.     for (n=1; n < maxlen; n++) {
  299.         if ( (rc = read(fd, &c, 1)) == 1) {
  300.             *ptr++ = c;
  301.             if (c == '\t') {
  302.                  *(ptr - 1) = '\0';
  303.                 break;
  304.             }
  305.         }
  306.         else if (rc == 0) {
  307.             if (n == 1)
  308.                 return(0);    /* EOF, no data read */
  309.             else
  310.                 break;        /* EOF, some data was read */
  311.         }
  312.         else
  313.             return(-1);        /* error */
  314.     }
  315.  
  316.     *ptr = 0;                 /* Tack a NULL on the end */
  317.     return(n);
  318. }
  319.  
  320.  
  321. /*
  322.  * readDelim reads data up to a delimiter or EOL (similar to readfield above)
  323.  */
  324.  
  325. int readDelim(fd, ptr, maxlen, delim)
  326. int    fd;
  327. char    *ptr;
  328. int     maxlen;
  329. char     delim;
  330. {
  331.     int n;
  332.     int rc;
  333.     char c;
  334.  
  335.     for (n=1; n < maxlen; n++) {
  336.         if ( (rc = read(fd, &c, 1)) == 1) {
  337.             *ptr++ = c;
  338.             if (c == delim  ||  c == '\n') {
  339.                  *(ptr - 1) = '\0';
  340.                 break;
  341.             }
  342.         }
  343.         else if (rc == 0) {
  344.             if (n == 1)
  345.                 return(0);    /* EOF, no data read */
  346.             else
  347.                 break;        /* EOF, some data was read */
  348.         }
  349.         else
  350.             return(-1);        /* error */
  351.     }
  352.  
  353.     *ptr = 0;                 /* Tack a NULL on the end */
  354.     return(n);
  355. }
  356.  
  357.  
  358. #ifdef NOT_NEEDED
  359. int
  360. sreadword(input, output, maxlen)
  361.   char *input;
  362.   char *output;
  363.   int maxlen;
  364. {
  365.      int n;
  366.      char c;
  367.      
  368.      for (n=0; n < maxlen; n++) {
  369.       c = *input++;
  370.       *output++ = c;
  371.       if (isspace(c)) {
  372.            *(output - 1) = '\0';
  373.            break;
  374.       }
  375.       
  376.       if (c == NULL) {
  377.            break;
  378.       }
  379.      }
  380.      
  381.      *output = '\0';                 /* Tack a NULL on the end */
  382.      return(n);
  383. }
  384. #endif /* NOT_NEEDED */
  385.  
  386. /*
  387.  * zapCRLF removes all carriage returns and linefeeds from a C-string.
  388.  */
  389.  
  390. void
  391. zapCRLF(inputline)
  392.   char *inputline;
  393. {
  394.      char *cp;
  395.  
  396.      cp = index(inputline, '\r');    /* Zap CR-LF */
  397.      if (cp != NULL)
  398.       *cp = '\0';
  399.      else {
  400.       cp = index(inputline, '\n');
  401.       if (cp != NULL)
  402.            *cp = '\0';
  403.      }
  404. }
  405.